﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Configuration.Install;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dependencies;
using System.Web.Http.Dispatcher;
using Kugar.Core.Configuration;
using Kugar.Core.ExtMethod;
using Kugar.Core.SystemManager;
using Kugar.Tool.DataSync.Client.BLL;
using Kugar.Tool.DataSync.Client.Filters;
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using Owin;

namespace Kugar.Tool.DataSync.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Contains("-service",StringComparer.CurrentCultureIgnoreCase))
            {
                SystemManager.InstallService("KugarDataSyncClient",Path.GetFullPath(System.Environment.CommandLine));
                SystemManager.StartService("KugarDataSyncClient");
                return;
            }

            

            int port = CustomConfigManager.Default.AppSettings.GetValueByName("HttpPort", "9090").ToInt();

            var webApp = WebApp.Start<Startup>(new StartOptions()
            {
                Port = port
            });
            
            Console.WriteLine("已开始监听");

            Console.ReadLine();

            webApp.Dispose();

            WebBLL.Plugin.Close();
        }
    }

    public class Startup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            // Configure Web API for self-host. 
            HttpConfiguration config = new HttpConfiguration();

            var pluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins");

            if (!Directory.Exists(pluginPath))
            {
                Directory.CreateDirectory(pluginPath);
            }

            WebBLL.Plugin.Initialize(config);

            config.Filters.Add(new GlobalFilterAttribute());

            //MefDependencySolver solver = new MefDependencySolver();
            //config.DependencyResolver = solver;


            config.Routes.MapHttpRoute(
                name: "ClientDefaultApi",
                routeTemplate: "Import/{appid}/{dataType}",
                defaults: new { controller = "home", action = "update" }
            );



            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "{controller}/{action}",
                defaults: new { controller = "home", action = "index" }
            );
            
            appBuilder.UseWebApi(config);

            var asse = typeof(Program).Assembly.GetReferencedAssemblies().ToArray();

            foreach (var assembly in asse)
            {
                AppDomain.CurrentDomain.Load(assembly);
            }

            //config.Services.Replace(typeof(IHttpControllerSelector),new MefControllerSelector(config));
           // config.Services.Replace(typeof(IHttpControllerTypeResolver),new MefHttpControllerTypeResolver());
            
        }

        private async Task onRun(IOwinContext context)
        {
            Console.WriteLine(context.Request.Uri.ToString());
        }
    }

    public class MefControllerSelector : DefaultHttpControllerSelector,IHttpControllerSelector
    {
        public MefControllerSelector(HttpConfiguration configuration) : base(configuration)
        {
        }
        

        public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            var controllers = GetControllerMapping();

            var routeData = request.GetRouteData();

            var controllerName = routeData.Values["controller"].ToString();

            HttpControllerDescriptor controllerDescriptor;

            if (controllers.TryGetValue(controllerName, out controllerDescriptor))
            {
                return controllerDescriptor;
            }

            return null;
        }

        public override string GetControllerName(HttpRequestMessage request)
        {
            return base.GetControllerName(request);
        }

        public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
        {
            return base.GetControllerMapping();
        }
    }

    //public class MefHttpControllerTypeResolver : DefaultHttpControllerTypeResolver
    //{
    //    public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
    //    {
    //        return base.GetControllerTypes(assembliesResolver);
    //    }

    //    protected override Predicate<Type> IsControllerTypePredicate { get; }
    //}


    public class MefDependencySolver : IDependencyResolver
    {
        private const string MefContainerKey = "JuCheap_MefContainerKey";

        #region IDependencyResolver Members  

        /// <summary>  
        /// GetService  
        /// </summary>  
        /// <param name="serviceType"></param>  
        /// <returns></returns>  
        public object GetService(Type serviceType)
        {
            string contractName = AttributedModelServices.GetContractName(serviceType);
            return WebBLL.Plugin.Container.GetExportedValueOrDefault<object>(contractName);
        }

        /// <summary>  
        /// GetServices  
        /// </summary>  
        /// <param name="serviceType"></param>  
        /// <returns></returns>  
        public IEnumerable<object> GetServices(Type serviceType)
        {
            return WebBLL.Plugin.Container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
        }

        /// <summary>  
        /// BeginScope  
        /// </summary>  
        /// <returns></returns>  
        public IDependencyScope BeginScope()
        {
            return new MefDependencySolver();
        }

        #endregion

        public void Dispose()
        {
            //ToDo  
        }
    }
}
